import os
import time
import json
import urllib3
from datetime import datetime, timedelta
from flask import jsonify
from basic.config import GlobalInfo, GlobalCfg
from basic.spider import Spider
from basic.messager import XiaoLB
from modules.module import WebsiteModule
from modules.sigalarm.sig import Sig, SigTestState


urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


class Sigalarm(WebsiteModule):

    def __init__(self, parent):
        super(Sigalarm, self).__init__(parent, 'sigalarm', '议题申报提醒服务，自动检测议题记事本，发生变动时提醒相关组织人员。')
        self.independent = True
        self.admin = ''
        self.sigs = []
        self.interval = 3600
        self.messager = None
        Sig.workpath = self.workspace.path

        self.last_ethpad_check_time = datetime.now() - timedelta(days=1)

        self.add_routes('sigalarm_state_cards', '/sigalarm_state_cards', self.get_check_state, ['GET'])
        self.add_routes('sigalarm_logs', '/sigalarm_logs', self.get_logs, ['GET'])

    def _send_msg(self, msg, recv, recv2=''):
        self.messager.send(msg, recv)

        if recv2 is None or recv2 == '':
            return
        self.messager.send(msg, recv2)

    def _refresh_config(self):
        with open(GlobalCfg.sigalarm_cfg, 'r') as f:
            config = json.load(f)

        Sig.spider = Spider(config['spider_proxies'])
        self.admin = config['admin']
        self.messager = XiaoLB(config['xiaolb_server'], config['xiaolb_auth'])
        self.sigs = [Sig(config) for config in config['sigmap']]
        self.interval = config['interval']

    def run(self):
        self.setproctitle("[devkit service process] - sigalarm")
        while True:
            if not self.enable():
                return
            
            self._refresh_config()
            for sig in self.sigs:
                self.runlog.log(f'开始检测{sig.name}。')
                
                self._alarm_meeting_check(sig)
                self._alarm_ethpad_check(sig)

                time.sleep(5)  # in case server busy.

            self.runlog.log(f'本轮检测结束。')
            time.sleep(1)

    def _alarm_meeting_check(self, sig):
        """
        检测是不是有新会议预定，并在当天提前5min发送提醒。
        """
        state, res = sig.detect_meeting()
        if state == SigTestState.NO_MEETING:
            self.runlog.log(f'未检测到新会议')
        elif state == SigTestState.NEW_MEETING:
            self.runlog.log(f'检测到新会议 {res}')
        elif state == SigTestState.HAVE_MEETING:
            self.runlog.log(f'已有新会议 {res}')
        else:
            msg = f'上会了上会了： {sig.name} {res}'
            self._send_msg(msg, sig.contacts, sig.contacts_group)


    def _alarm_ethpad_check(self, sig):
        """
        检测ethpad是否有变化，并发送提醒
        """
        if not sig.is_time_check_ethpad():
            return

        state, res = sig.detect_change()
        err_count = 0
        while state == SigTestState.ERROR:
            if err_count > 5:
                msg = f'检测{sig.name}时发生错误，尝试超过{err_count}次，进行跳过。'
                self.runlog.log(msg)
                self._send_msg(msg, self.admin)
                return
            self.runlog.log(f'检测{sig.name}时发生错误：{res}。等待1s再次尝试')
            time.sleep(1)
            err_count += 1

        now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        if state == SigTestState.FIRST_INIT:
            msg = f'SigAlarm 初始化：{sig.name}。'
            self.runlog.log(msg)
            self._send_msg(msg, sig.contacts, sig.contacts_group)

        elif state == SigTestState.SAME:
            self.runlog.log(f'{sig.name} 组未发生变动。')

        elif state == SigTestState.CHANGE:
            self.runlog.log(f'{sig.name} 组议题内容变动。')
            msg = f"议题申报提醒(beta) 检测时间: {now}\n" + \
                  f"SIG: {sig.name}\n" + \
                  f"URL: {sig.etherpad}\n" + \
                  f"DIFF:\n\n{res}\n\n\n" + \
                  f"（更多信息： {self.url} ）"
            self.runlog.log(msg)
            self._send_msg(msg, sig.contacts, sig.contacts_group)

    def enable(self):
        if GlobalCfg.sigalarm_cfg is None or GlobalCfg.sigalarm_cfg == "":
            return False
            
        if not os.access(GlobalCfg.sigalarm_cfg, os.F_OK):
            return False
            
        return True

    def homepage(self):
        return self.send_file('sigalarm.html')

    def get_check_state(self):
        sigs = self.sigs
        res = []
        for sig in sigs:
            info = {
                "name": sig.name,
                "url": sig.etherpad,
                "contacts": f"{sig.contacts}, {sig.contacts_group}",
                "last_time": sig.info['last_check'],
                "last_change": sig.info['last_change'],
                "meeting": sig.info['meeting'],
                "meeting_time": sig.info['meeting_time'],
            }
            res.append(info)

        return jsonify(res)
    
    def get_logs(self):
        with open(self.runlog.file, 'r', encoding='utf-8') as f:
            lines = f.readlines()
        
        return jsonify({'data': '<br>'.join(lines[-1:-500:-1])})


if __name__ == '__main__':
    Sigalarm(None).run()
    
    
    
    
    
    